# -*- coding:utf-8 -*-

# author: firstoneyuan
# email: devops_yj@163.com

"""
列表练习
1. 求100内的素数
  从2开始到自身的-1的数中找到一个能整除的=》从2开始到自身开平方的数中找到一个能整除的。
  一个合数一定可以分解成几个素数的乘积,也就是说,一个数如果能被一个素数整除就是合数。
2. 计算杨辉三角前6行
  第n行有n项,n是正整数
  第n行数字之和为2 n-1
  只要求打印出杨辉三角的数字即可
"""

# 1.求100内的素数
'''
一个数能被从2开始到自己的平方根的正整数整数整除,就是合数.

import math
n = 100
for x in range(2,n):
    for i in range(2,math.ceil(math.sqrt(x))):
        if x % i == 0:
            break
        else:
            print(x)
'''

'''
合数一定可以分解为几个质数的乘积

import math 

n = 100
primenumber = []
for x in range(2,n):
    for i in primenumber:
        if x % i == 0:
            break
        else:
            print(x)
            primenumber.append(x)

'''

'''
进一步缩小取模的范围

import math 
primenumber = []
flag = False

for x in range(2,10000):
    for i in primenumber:
        if x % i == 0:
            flag = True
            break
        if i >= math.ceil(math.sqrt(x)):
            flag = False
            break
        if not flag:
            print(x)
            primenumber.append(x)
'''

# 2. 计算杨辉三角前6行
'''
下一行依赖上一行所有元素,是上一行所有元素的两两相加的和,再在两头各加1.

triangle = [[1],[1,1]]
for i in range(2,6):
    cur = [1]
    pre = triangle[i-1]
    for j in range(len(pre)-1):
        cur.append(pre[j] + pre[j+1])
    cur.append(1)
    triangle.append(cur)
print(triangle)
'''

'''
计算杨辉三角前6行(方法1变体)

triangle = []
n = 6
for i in range(n):
    row = [1]
    triangle.append(row)
    if i == 0:
        continue
    for j in range(i-1):
        row.append(triangle[i-1][j]+triangle[i-1][j+1])
    row.append(1)
print(triangle)
'''

'''
计算杨辉三角前6行(方法2)    
    除了第一行以外,每一行每一个元素(包括两头的1)都是由上一行的元素相加得到。如何得到两头的1呢?

    目标是打印指定的行,所以算出一行就打印一行,不需要用一个大空间存储所有已经算出的行。
'''

'''
计算杨辉三角前6行(方法2-while)
n = 6
newline = [1]  #相当于计算好的第一行
print(newline)

for i in range(1,n):
    oldline = newline.copy() # 浅拷贝并补0
    oldline.append(0) # 尾部补0相当于两端补0.
    newline.clear() #使用append，要清除.

    offset = 0
    while offset <= i:
        newline.append(oldline[offset-1] + oldline[offset])
        offset += 1
    print(newline)

'''

'''
计算杨辉三角前6行(方法3)
    能不能一次性开辟每一行空间
        列表解析式
        循环迭代
        * ,乘法效率最高,减少每一次追加元素
            扩展带来的性能损耗
    能不能少算一半的数字(对称性)

triangle = []

n = 6

for i in range(n):
    row = [1] # 开始的1
    for k in range(i): # 中间填0,尾部填1
        row.append(1) if k == i-1 else row.append(0)
    triangle.append(row)
    if i == 0:
        continue
    for j in range(1,i//2+1): # i=2 第三行才能进来.
        #print(i,j)
        val = triangle[i-1][j-1]+ triangle[i-1][j]
        row[j] = val 
        # i 为3，j为0 1 2,循环1次
        # i 为3,j为0 1 2 3，循环1次.
        # i 为4, j为0 1 2 3 4,循环2次
        if i != 2*j: # 奇数个数的中点跳过
            row[-j-1] = val
print(triangle) 
'''



'''
计算杨辉三角前6行(方法3-变形)

triangle = []
n = 6
for i in range(n):
    row = [1] * (i+1)  # 一次性开辟
    triangle.append(row)
    for j in range(1,i//2+1): # i=2第三行才能进来.
        #print(i,j)
        val = triangle[i - 1][j-1] + triangle[i - 1][j]
        row[j] = val
        if i != 2*j: # 奇数个数的中点跳过
            row[-j-1] = val
print(triangle)
'''

'''
计算杨辉三角前6行(方法4)
    用上对称性
    方法3中为每一行都开辟空间,是否一次性开辟足够空间,只开辟一行重复利用.
'''
